#include "StdAfx.h"
#include "HttpStream.h"

namespace HttpProtocol
{

CHttpStream::CHttpStream(HINTERNET hFile, LPCSTR pstrVerb, LPCSTR pstrObject,
	CHttpConnect* pConnection) : m_hFile(hFile)
{
	_ASSERT(pstrVerb != NULL);
	_ASSERT(pstrObject != NULL);
	_ASSERT(pConnection != NULL);
}

CHttpStream::~CHttpStream(void)
{
}

BOOL CHttpStream::AddRequestHeaders(LPCSTR pstrHeaders,
	DWORD dwFlags/* = HTTP_ADDREQ_FLAG_ADD_IF_NEW*/,
	int dwHeadersLen/* = -1*/)
{
	_ASSERT(pstrHeaders != NULL);
	_ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
	_ASSERT(m_hFile != NULL);

	if (dwHeadersLen == -1)
		if (pstrHeaders == NULL)
			dwHeadersLen = 0;
		else
			dwHeadersLen = lstrlenA(pstrHeaders);

	BOOL bRet = HttpAddRequestHeadersA(m_hFile, pstrHeaders, dwHeadersLen, dwFlags);
	if (!bRet)
	{
		throw CHttpException(GetLastError());
	}

	return bRet;
}

BOOL CHttpStream::SendRequest(LPCSTR lpszHeaders, 
	DWORD dwHeadersLength,
	LPVOID lpOptional,
	DWORD dwOptionalLength)
{
	_ASSERT(m_hFile != NULL);

	BOOL bRet = HttpSendRequestA(m_hFile,
		lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);
	if (!bRet)
	{
		throw CHttpException(GetLastError());
	}

	return bRet;
}

BOOL CHttpStream::ReadStream(LPVOID lpBuffer,
	DWORD dwNumberOfBytesToRead,
	LPDWORD lpdwNumberOfBytesRead)
{
	_ASSERT(m_hFile != NULL);
	_ASSERT(lpBuffer != NULL);
	_ASSERT(dwNumberOfBytesToRead > 0);

	return InternetReadFile(m_hFile, lpBuffer,
		dwNumberOfBytesToRead, lpdwNumberOfBytesRead);
}

BOOL CHttpStream::QueryInfoStatusCode(DWORD& dwStatusCode) const
{
	_ASSERT(m_hFile != NULL);

	TCHAR szBuffer[80];
	DWORD dwLen = _countof(szBuffer);
	BOOL bRet;

	bRet = HttpQueryInfo(m_hFile, HTTP_QUERY_STATUS_CODE,
				szBuffer, &dwLen, NULL);

	if (bRet)
		dwStatusCode = (DWORD) _ttol(szBuffer);
	return bRet;
}

DWORD CHttpStream::GetLength() const
{
	_ASSERT(m_hFile != NULL);

	DWORD dwRet = 0;

	if (m_hFile != NULL)
	{
		if (!InternetQueryDataAvailable(m_hFile, &dwRet, 0, 0))
			dwRet = 0;
	}

	return dwRet;
}

BOOL CHttpStream::SendRequestEx(DWORD dwTotalLen,
	DWORD dwFlags/* = HSR_INITIATE*/,
	DWORD_PTR dwContext/* = 1*/)
{
	_ASSERT(m_hFile != NULL);

	INTERNET_BUFFERS buffer;
	memset(&buffer, 0, sizeof(buffer));
	buffer.dwStructSize = sizeof(buffer);
	buffer.dwBufferTotal = dwTotalLen;

	return HttpSendRequestEx(m_hFile, &buffer, NULL,
		dwFlags, dwContext);
}

BOOL CHttpStream::WriteString(LPCSTR pstr)
{
	_ASSERT(m_hFile != NULL);
	_ASSERT(pstr != NULL);
	
	LPCSTR lpBuf = pstr;
	size_t nCount = strlen(lpBuf);
	DWORD dwBytes;
	BOOL bRet;

	bRet = InternetWriteFile(m_hFile, lpBuf, (DWORD)nCount, &dwBytes);
	if (!bRet || dwBytes != nCount)
		return FALSE;

	return TRUE;
}

BOOL CHttpStream::EndRequest(DWORD dwFlags/* = 0*/,
	LPINTERNET_BUFFERS lpBuffIn/* = NULL*/,
	DWORD_PTR dwContext/* = 1*/)
{
	_ASSERT(m_hFile != NULL);

	return HttpEndRequest(m_hFile, lpBuffIn,
		dwFlags, dwContext);
}

BOOL CHttpStream::QueryInfo(DWORD dwInfoLevel,
	LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex) const
{
	_ASSERT(((HTTP_QUERY_HEADER_MASK & dwInfoLevel) <= HTTP_QUERY_MAX || 
		dwInfoLevel == HTTP_QUERY_CUSTOM) && dwInfoLevel != 0);
	_ASSERT(lpvBuffer != NULL && *lpdwBufferLength > 0);
	_ASSERT(m_hFile != NULL);

	return HttpQueryInfoA(m_hFile, dwInfoLevel, lpvBuffer,
		lpdwBufferLength, lpdwIndex);
}

BOOL CHttpStream::Release()
{
	return InternetCloseHandle(m_hFile);
}

}